﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Nb.Common.Ioc;
using Ninject;

namespace Nb.Common
{
    [TestClass]
    public class NbServiceProviderTest
    {
        [TestMethod]
        public void NoIoc_ShouldReturnDefaulProviders()
        {
            SetupWithoutIoc();
            DemoServiceManager.Reset();

            DemoServiceManager.AddProviderFunc(() => new DemoServiceProvider());
            DemoServiceManager.AddProviderFunc(() => new DemoServiceProvider2());

            var nbProviders = DemoServiceManager.GetProviders();
            Assert.AreEqual(2, nbProviders.Count);

            var demoService = DemoServiceManager.GetService();
            Assert.AreEqual("DemoService2", demoService.ShowName());
        }

        [TestMethod]
        public void WithIoc_ShouldReturnAllProviders()
        {
            SetupNinjectIoc();
            //bind customer providers
            var kernel = Singleton<IKernel>.Instance;
            kernel.Bind<INbProvider<IDemoService>>().To<DemoServiceProvider3>();
            kernel.Bind<INbProvider<IDemoService>>().To<DemoServiceProvider4>();

            DemoServiceManager.Reset();

            DemoServiceManager.AddProviderFunc(() => new DemoServiceProvider());
            DemoServiceManager.AddProviderFunc(() => new DemoServiceProvider2());


            var nbProviders = DemoServiceManager.GetProviders();
            Assert.AreEqual(4, nbProviders.Count);

            var demoService = DemoServiceManager.GetService();
            Assert.AreEqual("DemoService3", demoService.ShowName());
        }

        [TestMethod]
        public void WithIocRegister_ShouldReplaceDefaultFunc()
        {
            SetupNinjectIoc();

            //bind customer providers
            var kernel = Singleton<IKernel>.Instance;
            kernel.Bind<INbProvider<IDemoService>>().To<DemoServiceProvider2>();
            kernel.Bind<INbProvider<IDemoService>>().To<DemoServiceProvider3>();
            kernel.Bind<INbProvider<IDemoService>>().To<DemoServiceProvider4>();
            
            DemoServiceManager.Reset();

            DemoServiceManager.AddProviderFunc(() => new DemoServiceProvider());
            DemoServiceManager.AddProviderFunc(() => new DemoServiceProvider2());
            
            var nbProviders = DemoServiceManager.GetProviders();
            Assert.AreEqual(4, nbProviders.Count);

            var demoService = DemoServiceManager.GetService();
            Assert.AreEqual("DemoService3", demoService.ShowName());
        }

        private void SetupNinjectIoc()
        {
            var kernel = new StandardKernel();
            var ninjectServiceLocator = new NinjectServiceLocator(kernel);
            kernel.Bind<IServiceLocator>().To<NinjectServiceLocator>().InSingletonScope();

            //kernal
            //ninject service locator
            //core service provider
            Singleton<IKernel>.Instance = kernel;
            Singleton<IServiceLocator>.Instance = ninjectServiceLocator;
            CoreServiceProvider.Current = ninjectServiceLocator;
        }

        private void SetupWithoutIoc()
        {
            CoreServiceProvider.ResetToEmptyProvider();
        }


        #region demo

        public interface IDemoService
        {
            string ShowName();
        }

        public class DemoService : IDemoService
        {
            public string ShowName()
            {
                return "DemoService";
            }
        }
        public class DemoService2 : IDemoService
        {
            public string ShowName()
            {
                return "DemoService2";
            }
        }
        public class DemoService3 : IDemoService
        {
            public string ShowName()
            {
                return "DemoService3";
            }
        }

        public class DemoServiceProvider : BaseNbProvider<IDemoService>
        {
            public override IDemoService GetService()
            {
                return new DemoService();
            }

            public override int Priority
            {
                get { return base.Priority + 1; }
            }
        }
        public class DemoServiceProvider2 : BaseNbProvider<IDemoService>
        {
            public override IDemoService GetService()
            {
                return new DemoService2();
            }

            public override int Priority
            {
                get { return base.Priority + 2; }
            }
        }
        public class DemoServiceProvider3 : BaseNbProvider<IDemoService>
        {
            public override IDemoService GetService()
            {
                return new DemoService3();
            }

            public override int Priority
            {
                get { return base.Priority + 3; }
            }
        }
        public class DemoServiceProvider4 : BaseNbProvider<IDemoService>
        {
            public override IDemoService GetService()
            {
                return new DemoService3();
            }

            public override int Priority
            {
                get { return base.Priority - 1; }
            }
        }

        public class DemoServiceManager : NbServiceManager<IDemoService>
        {

        }

        #endregion
    }
}
